import { logger } from '$common';
import { Driver } from '../driver';
import { Command } from '$domain/service/commandBuilder';
import { DriverService } from '../driverService';
import { ICommandExecutor as ICommand, CommandExecutor, CommandExecuteBuilder, ExecutedResult } from '$domain/service/commandLineExecutor';

export abstract class DriverCommand implements ICommand {

  protected _driver: Driver;
  protected _commandExecutor: CommandExecutor;

  constructor(protected driverName: string, protected log = logger) {
    this._driver = DriverService.getByName(this.driverName);
  }

  async execute() {

    const { fullCommand: driverCommand } = this.buildCommand();

    const commandExecutor = this._commandExecutor = new CommandExecuteBuilder()
      .setWorkDir(this._driver.workDir)
      .setLogger(this.log)
      .build();

    let executeResult: ExecutedResult;
    try {
      executeResult = await commandExecutor.execute(driverCommand);
    } catch (e) {
      this.log.error(`😫 Driver(name=${this.driverName}) execution failed. e: ${e}`);
      throw e;
    }

    return executeResult;
  }

  async terminate() {
    if (this._commandExecutor) {
      await this._commandExecutor.terminate();
    }
  }

  protected abstract buildCommand(): Command;
}